/*
  ==============================================================================

    This file contains the basic framework code for a JUCE plugin editor.

  ==============================================================================
*/

#include "PluginEditor.h"
#include "PluginProcessor.h"

//==============================================================================
Dist_ampAudioProcessorEditor::Dist_ampAudioProcessorEditor(
    Dist_ampAudioProcessor& p)
    : AudioProcessorEditor(&p)
    , audioProcessor(p)
    , irFile(nullptr)
{
    const int borderWidth = 3;
    const int labelHeight = 20;
    const int knobHeight = 70;
    const int buttonHeight = 25;
    const int irLoaderHeight = 20;
    const int meterHeight = 200;
    const int meterWidth = 60;
    const auto backgroundColour = backGroundColour;

    StyledComponent::View topBox = { contourColour, contourColour, 20,
        borderWidth, TOP_BOX_HEIGHT, TOP_BOX_WIDTH,
        SEPERATE_WIDTH, SEPERATE_WIDTH };

    StyledComponent::View logoBox = { juce::Colours::transparentWhite,
        juce::Colours::transparentWhite,
        0,
        1,
        LOGO_BOX_HEIGHT,
        LOGO_BOX_WIDTH,
        188,
        256 };

    StyledComponent::View gainLabelBox = { juce::Colours::transparentWhite,
        juce::Colours::transparentWhite,
        0,
        0,
        labelHeight,
        knobHeight,
        2 * SEPERATE_WIDTH,
        2 * SEPERATE_WIDTH };

    StyledComponent::View gainBox = { juce::Colours::transparentWhite,
        juce::Colours::transparentWhite,
        0,
        0,
        knobHeight,
        knobHeight,
        2 * SEPERATE_WIDTH,
        gainLabelBox.getBottom() };

    StyledComponent::View boostButtonBox = { juce::Colours::transparentWhite,
        juce::Colours::transparentWhite,
        3,
        1,
        buttonHeight,
        buttonHeight,
        gainBox.left,
        gainBox.getBottom() + SEPERATE_WIDTH / 2 };

    StyledComponent::View boostLabelBox = { juce::Colours::transparentWhite,
        juce::Colours::transparentWhite,
        3,
        1,
        labelHeight,
        IR_BYPASS_LABEL_WIDTH,
        boostButtonBox.getRight(),
        gainBox.getBottom() + SEPERATE_WIDTH / 2 + 2.5 };

    StyledComponent::View bassLabelBox = { juce::Colours::transparentWhite,
        juce::Colours::transparentWhite,
        0,
        0,
        labelHeight,
        knobHeight,
        gainBox.getRight() + 2 * SEPERATE_WIDTH,
        2 * SEPERATE_WIDTH };

    StyledComponent::View bassBox = { juce::Colours::transparentWhite,
        juce::Colours::transparentWhite,
        0,
        0,
        knobHeight,
        knobHeight,
        gainBox.getRight() + 2 * SEPERATE_WIDTH,
        bassLabelBox.getBottom() };

    StyledComponent::View channelSelectButtonBox = { juce::Colours::transparentWhite,
        juce::Colours::transparentWhite,
        3,
        1,
        buttonHeight,
        buttonHeight,
        bassBox.left,
        bassBox.getBottom() + SEPERATE_WIDTH / 2 };

    StyledComponent::View channelSelectLabelBox = { juce::Colours::transparentWhite,
        juce::Colours::transparentWhite,
        3,
        1,
        labelHeight,
        150,
        channelSelectButtonBox.getRight(),
        bassBox.getBottom() + SEPERATE_WIDTH / 2 + 2.5 };

    StyledComponent::View channel1LedBox = { juce::Colours::transparentWhite,
        juce::Colours::transparentWhite,
        0,
        0,
        labelHeight,
        labelHeight,
        channelSelectLabelBox.getRight(),
        bassBox.getBottom() + SEPERATE_WIDTH / 2 + 2.5 };

    StyledComponent::View channel1LedLabelBox = { juce::Colours::transparentWhite,
        juce::Colours::transparentWhite,
        3,
        1,
        labelHeight,
        IR_BYPASS_LABEL_WIDTH,
        channel1LedBox.getRight() + 2.5,
        gainBox.getBottom() + SEPERATE_WIDTH / 2 + 2.5 };

    StyledComponent::View channel2LedBox = { juce::Colours::transparentWhite,
        juce::Colours::transparentWhite,
        0,
        0,
        labelHeight,
        labelHeight,
        channelSelectLabelBox.getRight(),
        bassBox.getBottom() + SEPERATE_WIDTH / 2 + 5 + labelHeight };

    StyledComponent::View channel2LedLabelBox = { juce::Colours::transparentWhite,
        juce::Colours::transparentWhite,
        3,
        1,
        labelHeight,
        IR_BYPASS_LABEL_WIDTH,
        channel2LedBox.getRight() + 2.5,
        bassBox.getBottom() + SEPERATE_WIDTH / 2 + 5 + labelHeight };

    StyledComponent::View midLabelBox = { juce::Colours::transparentWhite,
        juce::Colours::transparentWhite,
        0,
        0,
        labelHeight,
        knobHeight,
        bassBox.getRight() + 2 * SEPERATE_WIDTH,
        2 * SEPERATE_WIDTH };

    StyledComponent::View midBox = { juce::Colours::transparentWhite,
        juce::Colours::transparentWhite,
        0,
        0,
        knobHeight,
        knobHeight,
        bassBox.getRight() + 2 * SEPERATE_WIDTH,
        midLabelBox.getBottom() };

    StyledComponent::View trebleLabelBox = { juce::Colours::transparentWhite,
        juce::Colours::transparentWhite,
        0,
        0,
        labelHeight,
        knobHeight,
        midBox.getRight() + 2 * SEPERATE_WIDTH,
        2 * SEPERATE_WIDTH };

    StyledComponent::View trebleBox = { juce::Colours::transparentWhite,
        juce::Colours::transparentWhite,
        0,
        0,
        knobHeight,
        knobHeight,
        midBox.getRight() + 2 * SEPERATE_WIDTH,
        trebleLabelBox.getBottom() };

    StyledComponent::View presenceLabelBox = { juce::Colours::transparentWhite,
        juce::Colours::transparentWhite,
        0,
        0,
        labelHeight,
        knobHeight,
        trebleBox.getRight() + 2 * SEPERATE_WIDTH,
        2 * SEPERATE_WIDTH };

    StyledComponent::View presenceBox = { juce::Colours::transparentWhite,
        juce::Colours::transparentWhite,
        0,
        0,
        knobHeight,
        knobHeight,
        trebleBox.getRight() + 2 * SEPERATE_WIDTH,
        presenceLabelBox.getBottom() };

    StyledComponent::View masterLabelBox = { juce::Colours::transparentWhite,
        juce::Colours::transparentWhite,
        0,
        0,
        labelHeight,
        knobHeight,
        presenceBox.getRight() + 2 * SEPERATE_WIDTH,
        2 * SEPERATE_WIDTH };

    StyledComponent::View masterBox = { juce::Colours::transparentWhite,
        juce::Colours::transparentWhite,
        0,
        0,
        knobHeight,
        knobHeight,
        presenceBox.getRight() + 2 * SEPERATE_WIDTH,
        masterLabelBox.getBottom() };

    StyledComponent::View irLabelBox = { juce::Colours::transparentWhite,
        contourColour,
        3,
        1,
        labelHeight,
        IR_LABEL_WIDTH,
        2 * SEPERATE_WIDTH,
        topBox.getBottom() - 3 * SEPERATE_WIDTH - labelHeight };

    StyledComponent::View irButtonBox = { juce::Colours::transparentWhite,
        juce::Colours::transparentWhite,
        3,
        1,
        buttonHeight,
        IR_BUTTON_WIDTH,
        irLabelBox.getRight() + SEPERATE_WIDTH,
        topBox.getBottom() - 3 * SEPERATE_WIDTH - (buttonHeight + labelHeight) / 2 };

    StyledComponent::View irBypassButtonBox = {
        juce::Colours::transparentWhite,
        juce::Colours::transparentWhite,
        3,
        1,
        buttonHeight,
        buttonHeight,
        irButtonBox.getRight() + SEPERATE_WIDTH,
        topBox.getBottom() - 3 * SEPERATE_WIDTH - (buttonHeight + labelHeight) / 2
    };

    StyledComponent::View irBypassLabelBox = {
        juce::Colours::transparentWhite,
        juce::Colours::transparentWhite,
        3,
        1,
        labelHeight,
        IR_BYPASS_LABEL_WIDTH,
        irBypassButtonBox.getRight(),
        topBox.getBottom() - 3 * SEPERATE_WIDTH - labelHeight
    };

    StyledComponent::View inputMeterBox = { juce::Colours::transparentWhite,
        contourColour,
        3,
        1,
        meterHeight,
        meterWidth,
        2 * SEPERATE_WIDTH,
        irLabelBox.top - 2 * SEPERATE_WIDTH - meterHeight };

    StyledComponent::View inputAlarmBox = { juce::Colours::transparentWhite,
        contourColour,
        3,
        1,
        SEPERATE_WIDTH,
        2 * SEPERATE_WIDTH,
        2 * SEPERATE_WIDTH,
        inputMeterBox.top - SEPERATE_WIDTH };

    StyledComponent::View inputLabelBox = { juce::Colours::transparentWhite,
        juce::Colours::transparentWhite,
        3,
        1,
        labelHeight,
        knobHeight,
        inputMeterBox.getRight() + SEPERATE_WIDTH,
        inputMeterBox.top };

    StyledComponent::View inputKnobBox = { juce::Colours::transparentWhite,
        juce::Colours::transparentWhite,
        3,
        1,
        knobHeight,
        knobHeight,
        inputMeterBox.getRight() + SEPERATE_WIDTH,
        inputLabelBox.getBottom() };

    StyledComponent::View outputMeterBox = {
        juce::Colours::transparentWhite,
        contourColour,
        3,
        1,
        meterHeight,
        meterWidth,
        TOP_BOX_WIDTH - 2 * SEPERATE_WIDTH - meterWidth,
        irLabelBox.top - 2 * SEPERATE_WIDTH - meterHeight
    };

    StyledComponent::View outputAlarmBox = { juce::Colours::transparentWhite,
        contourColour,
        3,
        1,
        SEPERATE_WIDTH,
        2 * SEPERATE_WIDTH,
        TOP_BOX_WIDTH - 2 * SEPERATE_WIDTH - meterWidth,
        outputMeterBox.top - SEPERATE_WIDTH };

    StyledComponent::View outputLabelBox = { juce::Colours::transparentWhite,
        juce::Colours::transparentWhite,
        3,
        1,
        labelHeight,
        knobHeight,
        outputMeterBox.left - SEPERATE_WIDTH - knobHeight,
        outputMeterBox.top };

    StyledComponent::View outputKnobBox = { juce::Colours::transparentWhite,
        juce::Colours::transparentWhite,
        3,
        1,
        knobHeight,
        knobHeight,
        outputMeterBox.left - SEPERATE_WIDTH - knobHeight,
        outputLabelBox.getBottom() };

    auto topBoxComponent = std::make_shared<StyledComponent>(topBox);
    auto logoBoxComponent = std::make_shared<StyledComponent>(logoBox);
    auto gainLabelComponent = std::make_shared<StyledComponent>(gainLabelBox);
    auto gainBoxComponent = std::make_shared<StyledComponent>(gainBox);
    auto boostButtonBoxComponent = std::make_shared<StyledComponent>(boostButtonBox);
    auto boostLabelComponent = std::make_shared<StyledComponent>(boostLabelBox);
    auto channelSelectButtonBoxComponent = std::make_shared<StyledComponent>(channelSelectButtonBox);
    auto channelSelectLabelComponent = std::make_shared<StyledComponent>(channelSelectLabelBox);
    auto channel1LedComponent = std::make_shared<StyledComponent>(channel1LedBox);
    auto channel2LedComponent = std::make_shared<StyledComponent>(channel2LedBox);
    auto channel1LedLabelComponent = std::make_shared<StyledComponent>(channel1LedLabelBox);
    auto channel2LedLabelComponent = std::make_shared<StyledComponent>(channel2LedLabelBox);
    auto presenceLabelComponent = std::make_shared<StyledComponent>(presenceLabelBox);
    auto presenceBoxComponent = std::make_shared<StyledComponent>(presenceBox);
    auto bassLabelComponent = std::make_shared<StyledComponent>(bassLabelBox);
    auto bassBoxComponent = std::make_shared<StyledComponent>(bassBox);
    auto midLabelComponent = std::make_shared<StyledComponent>(midLabelBox);
    auto midBoxComponent = std::make_shared<StyledComponent>(midBox);
    auto trebleLabelComponent = std::make_shared<StyledComponent>(trebleLabelBox);
    auto trebleBoxComponent = std::make_shared<StyledComponent>(trebleBox);
    auto masterLabelComponent = std::make_shared<StyledComponent>(masterLabelBox);
    auto masterBoxComponent = std::make_shared<StyledComponent>(masterBox);
    auto irLabelBoxComponent = std::make_shared<StyledComponent>(irLabelBox);
    auto irButtonBoxComponent = std::make_shared<StyledComponent>(irButtonBox);
    auto irBypassButtonBoxComponent = std::make_shared<StyledComponent>(irBypassButtonBox);
    auto irBypassLabelBoxComponent = std::make_shared<StyledComponent>(irBypassLabelBox);
    auto inputMeterBoxComponent = std::make_shared<StyledComponent>(inputMeterBox);
    auto inputAlarmBoxComponent = std::make_shared<StyledComponent>(inputAlarmBox);
    auto inputLabelComponent = std::make_shared<StyledComponent>(inputLabelBox);
    auto inputKnobComponent = std::make_shared<StyledComponent>(inputKnobBox);
    auto outputMeterBoxComponent = std::make_shared<StyledComponent>(outputMeterBox);
    auto outputLabelComponent = std::make_shared<StyledComponent>(outputLabelBox);
    auto outputKnobComponent = std::make_shared<StyledComponent>(outputKnobBox);
    auto outputAlarmBoxComponent = std::make_shared<StyledComponent>(outputAlarmBox);

    const juce::Font sliderLabelFont(
        juce::Font("Arial", 17.0f, juce::Font::plain));
    const juce::Font smallLabelFont(
        juce::Font("Arial", 15.0f, juce::Font::plain));

    topComponent.styles.backgroundColor = juce::Colours::black;
    topComponent.styles.height = TOP_COMPONENT_HEIGHT;
    topComponent.styles.width = TOP_COMPONENT_WIDTH;
    topComponent.styles.left = 0;
    topComponent.styles.top = 0;
    addAndMakeVisible(topComponent);
    topComponent.addChild(topBoxComponent);

    gainLabel = std::make_shared<juce::Label>();
    gainLabel->setText(GAIN_NAME, juce::dontSendNotification);
    gainLabel->setJustificationType(juce::Justification::centredBottom);
    gainLabel->setFont(sliderLabelFont);
    gainLabel->setColour(juce::Label::textColourId, contourColour);

    gainKnob = std::make_shared<juce::Slider>();
    gainValue = std::make_unique<SliderAttachment>(audioProcessor.treeState,
        GAIN_ID, *gainKnob);
    gainKnob->setSliderStyle(juce::Slider::RotaryVerticalDrag);
    gainKnob->setRange(0.0, 10.0, 0.1);
    gainKnob->setTextBoxStyle(juce::Slider::NoTextBox, false, 0, 0);
    gainKnob->setPopupDisplayEnabled(true, true, this);
    gainKnob->setLookAndFeel(&dialLookAndFeel);

    boostButton = std::make_shared<juce::ToggleButton>();
    auto boostButtonState = audioProcessor.customVariables.getProperty(BOOST_ID);
    boostButton->setToggleState(boostButtonState == "true" ? true : false,
        juce::dontSendNotification);
    boostButton->setLookAndFeel(&dialLookAndFeel);
    boostButton->onClick = [this]() {
        auto enable = boostButton->getToggleState();
        audioProcessor.enableBoost(enable);
        audioProcessor.customVariables.setProperty(
            BOOST_ID, enable == true ? "true" : "false", nullptr);
    };
    boostLabel = std::make_shared<juce::Label>();
    boostLabel->setText("BOOST", juce::dontSendNotification);
    boostLabel->setJustificationType(juce::Justification::bottomLeft);
    boostLabel->setFont(smallLabelFont);
    boostLabel->setColour(juce::Label::textColourId, contourColour);

    channelSelectButton = std::make_shared<juce::ToggleButton>();
    auto currentCh = audioProcessor.customVariables.getProperty(CHANNEL_ID);
    auto channelState = currentCh == "2" ? true : false;
    channelSelectButton->setToggleState(channelState,
        juce::dontSendNotification);
    channelSelectButton->setLookAndFeel(&dialLookAndFeel);
    channelSelectButton->onClick = [this]() {
        auto ch2Enable = channelSelectButton->getToggleState();
        int ch = ch2Enable ? 2 : 1;
        audioProcessor.setChannel(ch);
        audioProcessor.customVariables.setProperty(CHANNEL_ID, juce::String(ch), nullptr);
        channel1Led->setState(!ch2Enable);
        channel2Led->setState(ch2Enable);
    };
    channelSelectLabel = std::make_shared<juce::Label>();
    channelSelectLabel->setText("CHANNEL SELECT", juce::dontSendNotification);
    channelSelectLabel->setJustificationType(juce::Justification::bottomLeft);
    channelSelectLabel->setFont(smallLabelFont);
    channelSelectLabel->setColour(juce::Label::textColourId, contourColour);
    channel1Led = std::make_shared<juce::RoundLED>(true, juce::Colours::green);
    channel1Led->setState(!channelState);
    channel2Led = std::make_shared<juce::RoundLED>(false, juce::Colours::red);
    channel2Led->setState(channelState);
    channel1LedLabel = std::make_shared<juce::Label>();
    channel1LedLabel->setText("CRUNCH", juce::dontSendNotification);
    channel1LedLabel->setJustificationType(juce::Justification::bottomLeft);
    channel1LedLabel->setFont(smallLabelFont);
    channel1LedLabel->setColour(juce::Label::textColourId, contourColour);
    channel2LedLabel = std::make_shared<juce::Label>();
    channel2LedLabel->setText("LEAD", juce::dontSendNotification);
    channel2LedLabel->setJustificationType(juce::Justification::bottomLeft);
    channel2LedLabel->setFont(smallLabelFont);
    channel2LedLabel->setColour(juce::Label::textColourId, contourColour);

    presenceLabel = std::make_shared<juce::Label>();
    presenceLabel->setText(PRESENCE_NAME, juce::dontSendNotification);
    presenceLabel->setJustificationType(juce::Justification::centredBottom);
    presenceLabel->setFont(sliderLabelFont);
    presenceLabel->setColour(juce::Label::textColourId, contourColour);

    presenceKnob = std::make_shared<juce::Slider>();
    presenceValue = std::make_unique<SliderAttachment>(
        audioProcessor.treeState, PRESENCE_ID, *presenceKnob);
    presenceKnob->setSliderStyle(juce::Slider::RotaryVerticalDrag);
    presenceKnob->setRange(0.0, 10.0, 0.1);
    presenceKnob->setTextBoxStyle(juce::Slider::NoTextBox, false, 0, 0);
    presenceKnob->setPopupDisplayEnabled(true, true, this);
    presenceKnob->setLookAndFeel(&dialLookAndFeel);

    bassLabel = std::make_shared<juce::Label>();
    bassLabel->setText(BASS_NAME, juce::dontSendNotification);
    bassLabel->setJustificationType(juce::Justification::centredBottom);
    bassLabel->setFont(sliderLabelFont);
    bassLabel->setColour(juce::Label::textColourId, contourColour);

    bassKnob = std::make_shared<juce::Slider>();
    bassValue = std::make_unique<SliderAttachment>(audioProcessor.treeState,
        BASS_ID, *bassKnob);
    bassKnob->setSliderStyle(juce::Slider::RotaryVerticalDrag);
    bassKnob->setRange(0.0, 10.0, 0.1);
    bassKnob->setTextBoxStyle(juce::Slider::NoTextBox, false, 0, 0);
    bassKnob->setPopupDisplayEnabled(true, true, this);
    bassKnob->setLookAndFeel(&dialLookAndFeel);

    midLabel = std::make_shared<juce::Label>();
    midLabel->setText(MID_NAME, juce::dontSendNotification);
    midLabel->setJustificationType(juce::Justification::centredBottom);
    midLabel->setFont(sliderLabelFont);
    midLabel->setColour(juce::Label::textColourId, contourColour);

    midKnob = std::make_shared<juce::Slider>();
    midValue = std::make_unique<SliderAttachment>(audioProcessor.treeState,
        MID_ID, *midKnob);
    midKnob->setSliderStyle(juce::Slider::RotaryVerticalDrag);
    midKnob->setRange(0.0, 10.0, 0.1);
    midKnob->setTextBoxStyle(juce::Slider::NoTextBox, false, 0, 0);
    midKnob->setPopupDisplayEnabled(true, true, this);
    midKnob->setLookAndFeel(&dialLookAndFeel);

    trebleLabel = std::make_shared<juce::Label>();
    trebleLabel->setText(TREBLE_NAME, juce::dontSendNotification);
    trebleLabel->setJustificationType(juce::Justification::centredBottom);
    trebleLabel->setFont(sliderLabelFont);
    trebleLabel->setColour(juce::Label::textColourId, contourColour);

    trebleKnob = std::make_shared<juce::Slider>();
    trebleValue = std::make_unique<SliderAttachment>(audioProcessor.treeState,
        TREBLE_ID, *trebleKnob);
    trebleKnob->setSliderStyle(juce::Slider::RotaryVerticalDrag);
    trebleKnob->setRange(0.0, 10.0, 0.1);
    trebleKnob->setTextBoxStyle(juce::Slider::NoTextBox, false, 0, 0);
    trebleKnob->setPopupDisplayEnabled(true, true, this);
    trebleKnob->setLookAndFeel(&dialLookAndFeel);

    masterLabel = std::make_shared<juce::Label>();
    masterLabel->setText(MASTER_NAME, juce::dontSendNotification);
    masterLabel->setJustificationType(juce::Justification::centredBottom);
    masterLabel->setFont(sliderLabelFont);
    masterLabel->setColour(juce::Label::textColourId, contourColour);

    masterKnob = std::make_shared<juce::Slider>();
    masterValue = std::make_unique<SliderAttachment>(audioProcessor.treeState,
        MASTER_ID, *masterKnob);
    masterKnob->setSliderStyle(juce::Slider::RotaryVerticalDrag);
    masterKnob->setRange(0.0, 10.0, 0.1);
    masterKnob->setTextBoxStyle(juce::Slider::NoTextBox, false, 0, 0);
    masterKnob->setPopupDisplayEnabled(true, true, this);
    masterKnob->setLookAndFeel(&dialLookAndFeel);

    irLabel = std::make_shared<juce::Label>();
    irFile = std::make_shared<juce::String>(
        audioProcessor.customVariables.getProperty(IR_ID).toString());
    if (*irFile == "")
        irLabel->setText("Select IR file...", juce::dontSendNotification);
    else
        irLabel->setText(*irFile, juce::dontSendNotification);
    irLabel->setJustificationType(juce::Justification::centredBottom);
    irLabel->setFont(smallLabelFont);
    irLabel->setColour(juce::Label::textColourId, contourColour);

    irButton = std::make_shared<juce::TextButton>();
    irButton->setButtonText("Load");
    irButton->setColour(juce::TextButton::buttonColourId, backgroundColour);
    irButton->onClick = [this] { irButtonClicked(); };

    irBypassButton = std::make_shared<juce::ToggleButton>();
    irBypassButton->onClick = [this] {
        auto bypass = irBypassButton->getToggleState();
        audioProcessor.bypassIR(bypass);
        audioProcessor.customVariables.setProperty(
            IR_BYPASS_ID, bypass == true ? "true" : "false", nullptr);
    };
    auto irBypassState = audioProcessor.customVariables.getProperty(IR_BYPASS_ID);
    irBypassButton->setToggleState(irBypassState == "true" ? true : false,
        juce::dontSendNotification);
    irBypassLabel = std::make_shared<juce::Label>();
    irBypassLabel->setText("Bypass IR", juce::dontSendNotification);
    irBypassLabel->setJustificationType(juce::Justification::bottomLeft);
    irBypassLabel->setFont(smallLabelFont);
    irBypassLabel->setColour(juce::Label::textColourId, contourColour);

    levelMeterIn = std::make_shared<juce::LevelMeter>(
        [&]() { return audioProcessor.getRMSValue(true); });
    levelAlarmIn = std::make_shared<juce::LevelAlarm>(
        [&]() { return audioProcessor.getPeakValue(true); });

    inputLevelLabel = std::make_shared<juce::Label>();
    inputLevelLabel->setText(INPUT_NAME, juce::dontSendNotification);
    inputLevelLabel->setJustificationType(juce::Justification::centredBottom);
    inputLevelLabel->setFont(sliderLabelFont);
    inputLevelLabel->setColour(juce::Label::textColourId, contourColour);

    inputKnob = std::make_shared<juce::Slider>();
    inputValue = std::make_unique<SliderAttachment>(audioProcessor.treeState,
        INPUT_ID, *inputKnob);
    inputKnob->setSliderStyle(juce::Slider::RotaryVerticalDrag);
    inputKnob->setRange(0.0, 10.0, 0.1);
    inputKnob->setTextBoxStyle(juce::Slider::NoTextBox, false, 0, 0);
    inputKnob->setPopupDisplayEnabled(true, true, this);
    inputKnob->setLookAndFeel(&dialLookAndFeel);

    levelMeterOut = std::make_shared<juce::LevelMeter>(
        [&]() { return audioProcessor.getRMSValue(false); });
    levelAlarmOut = std::make_shared<juce::LevelAlarm>(
        [&]() { return audioProcessor.getPeakValue(false); });

    outputLevelLabel = std::make_shared<juce::Label>();
    outputLevelLabel->setText(OUTPUT_NAME, juce::dontSendNotification);
    outputLevelLabel->setJustificationType(juce::Justification::centredBottom);
    outputLevelLabel->setFont(sliderLabelFont);
    outputLevelLabel->setColour(juce::Label::textColourId, contourColour);

    outputKnob = std::make_shared<juce::Slider>();
    outputValue = std::make_unique<SliderAttachment>(audioProcessor.treeState,
        OUTPUT_ID, *outputKnob);
    outputKnob->setSliderStyle(juce::Slider::RotaryVerticalDrag);
    outputKnob->setRange(0.0, 10.0, 0.1);
    outputKnob->setTextBoxStyle(juce::Slider::NoTextBox, false, 0, 0);
    outputKnob->setPopupDisplayEnabled(true, true, this);
    outputKnob->setLookAndFeel(&dialLookAndFeel);

    auto backgroundImage = juce::ImageCache::getFromMemory(
        BinaryData::blackMetalTexture_png, BinaryData::blackMetalTexture_pngSize);
    auto backgroundImageComponent = std::make_shared<juce::ImageComponent>();
    backgroundImageComponent->setImage(backgroundImage);
    backgroundImageComponent->setBounds(topBoxComponent->getBounds());

    auto logoImage = juce::ImageCache::getFromMemory(
        BinaryData::orodruin_png, BinaryData::orodruin_pngSize);
    auto logoImageComponent = std::make_shared<juce::ImageComponent>();
    logoImageComponent->setImage(logoImage);

    topBoxComponent->addChild(backgroundImageComponent);

    topBoxComponent->addChild(logoBoxComponent);

    topBoxComponent->addChild(gainLabelComponent);
    topBoxComponent->addChild(gainBoxComponent);

    topBoxComponent->addChild(boostButtonBoxComponent);
    topBoxComponent->addChild(boostLabelComponent);

    topBoxComponent->addChild(channelSelectButtonBoxComponent);
    topBoxComponent->addChild(channelSelectLabelComponent);
    topBoxComponent->addChild(channel1LedComponent);
    topBoxComponent->addChild(channel2LedComponent);
    topBoxComponent->addChild(channel1LedLabelComponent);
    topBoxComponent->addChild(channel2LedLabelComponent);

    topBoxComponent->addChild(presenceLabelComponent);
    topBoxComponent->addChild(presenceBoxComponent);

    topBoxComponent->addChild(bassLabelComponent);
    topBoxComponent->addChild(bassBoxComponent);

    topBoxComponent->addChild(midLabelComponent);
    topBoxComponent->addChild(midBoxComponent);

    topBoxComponent->addChild(trebleLabelComponent);
    topBoxComponent->addChild(trebleBoxComponent);

    topBoxComponent->addChild(masterLabelComponent);
    topBoxComponent->addChild(masterBoxComponent);

    topBoxComponent->addChild(irLabelBoxComponent);
    topBoxComponent->addChild(irButtonBoxComponent);
    topBoxComponent->addChild(irBypassButtonBoxComponent);
    topBoxComponent->addChild(irBypassLabelBoxComponent);

    topBoxComponent->addChild(inputMeterBoxComponent);
    topBoxComponent->addChild(inputAlarmBoxComponent);
    topBoxComponent->addChild(inputLabelComponent);
    topBoxComponent->addChild(inputKnobComponent);

    topBoxComponent->addChild(outputMeterBoxComponent);
    topBoxComponent->addChild(outputAlarmBoxComponent);
    topBoxComponent->addChild(outputLabelComponent);
    topBoxComponent->addChild(outputKnobComponent);

    logoBoxComponent->addChild(logoImageComponent);

    gainLabelComponent->addChild(gainLabel);
    gainBoxComponent->addChild(gainKnob);

    boostButtonBoxComponent->addChild(boostButton);
    boostLabelComponent->addChild(boostLabel);

    channelSelectButtonBoxComponent->addChild(channelSelectButton);
    channelSelectLabelComponent->addChild(channelSelectLabel);
    channel1LedComponent->addChild(channel1Led);
    channel2LedComponent->addChild(channel2Led);
    channel1LedLabelComponent->addChild(channel1LedLabel);
    channel2LedLabelComponent->addChild(channel2LedLabel);

    presenceLabelComponent->addChild(presenceLabel);
    presenceBoxComponent->addChild(presenceKnob);

    bassLabelComponent->addChild(bassLabel);
    bassBoxComponent->addChild(bassKnob);

    midLabelComponent->addChild(midLabel);
    midBoxComponent->addChild(midKnob);

    trebleLabelComponent->addChild(trebleLabel);
    trebleBoxComponent->addChild(trebleKnob);

    masterLabelComponent->addChild(masterLabel);
    masterBoxComponent->addChild(masterKnob);

    irLabelBoxComponent->addChild(irLabel);
    irButtonBoxComponent->addChild(irButton);
    irBypassButtonBoxComponent->addChild(irBypassButton);
    irBypassLabelBoxComponent->addChild(irBypassLabel);

    inputMeterBoxComponent->addChild(levelMeterIn);
    inputAlarmBoxComponent->addChild(levelAlarmIn);
    inputLabelComponent->addChild(inputLevelLabel);
    inputKnobComponent->addChild(inputKnob);

    outputMeterBoxComponent->addChild(levelMeterOut);
    outputAlarmBoxComponent->addChild(levelAlarmOut);
    outputLabelComponent->addChild(outputLevelLabel);
    outputKnobComponent->addChild(outputKnob);

    setSize(TOP_COMPONENT_WIDTH, TOP_COMPONENT_HEIGHT);
    startTimerHz(24);
}

Dist_ampAudioProcessorEditor::~Dist_ampAudioProcessorEditor()
{
    gainKnob->setLookAndFeel(nullptr);
    boostButton->setLookAndFeel(nullptr);
    channelSelectButton->setLookAndFeel(nullptr);
    presenceKnob->setLookAndFeel(nullptr);
    bassKnob->setLookAndFeel(nullptr);
    midKnob->setLookAndFeel(nullptr);
    trebleKnob->setLookAndFeel(nullptr);
    inputKnob->setLookAndFeel(nullptr);
}

//==============================================================================
void Dist_ampAudioProcessorEditor::paint(juce::Graphics& g)
{
    g.fillAll(backGroundColour);
}

void Dist_ampAudioProcessorEditor::resized()
{
    topComponent.setBounds(getLocalBounds());
}

void Dist_ampAudioProcessorEditor::timerCallback()
{
    levelMeterIn->timerCallback();
}

void Dist_ampAudioProcessorEditor::irButtonClicked()
{
    if (*irFile == "")
        irFileChooser = std::make_unique<juce::FileChooser>(
            "Select IR file...",
            juce::File::getSpecialLocation(juce::File::userDocumentsDirectory),
            "*.wav");
    else
        irFileChooser = std::make_unique<juce::FileChooser>(
            "Select IR file...", juce::File(*irFile), "*.wav");
    auto folderChooserFlags = juce::FileBrowserComponent::openMode | juce::FileBrowserComponent::canSelectFiles;
    irFileChooser->launchAsync(
        folderChooserFlags, [this](const juce::FileChooser& chooser) {
            juce::File result = chooser.getResult();
            if (result.getFileName() == "")
                return;
            irFile = std::make_shared<juce::String>(result.getFullPathName());
            audioProcessor.customVariables.setProperty(IR_ID, *irFile, nullptr);
            audioProcessor.setIrFile(result);
            irLabel->setText(*irFile, juce::NotificationType::dontSendNotification);
        });
}
